/*
 * OPIAM Suite
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */

package opiam.admin.applis.demo.actions;

import opiam.admin.applis.demo.beans.Person;
import opiam.admin.applis.demo.utils.GenerateTree;

import opiam.admin.faare.MessageUtil;
import opiam.admin.faare.config.javabeans.JBProfile;
import opiam.admin.faare.exception.AuthenticationFailureException;
import opiam.admin.faare.service.UserContext;
import opiam.admin.faare.service.services.StandardService;
import opiam.admin.faare.service.services.views.TreeNode;
import opiam.admin.faare.service.services.views.ViewGenerator;
import opiam.admin.faare.struts.managers.AppliParametersManager;
import opiam.admin.faare.struts.utils.SessionContext;

import org.apache.log4j.Logger;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import java.io.IOException;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;


/**
 * This class allows to log on.
 *
 * This Action class can not inherit from SecureAction class because the user
 * is not connected yet, or the SecureAction class checks that the user is
 * connected before calling the action methods.
 */
public class LogonAction extends Action
{
    /** Instance of the log4j logger.
     * Used to generate the execution traces. */
    private static Logger _logger =
        Logger.getLogger(LogonAction.class.getName());

    /**
     * This method is called to execute the action.
     *
     * @param mapping              Struts mapping data.
     * @param actionForm           FormBean associated with the action.
     * @param request              HTTP request.
     * @param httpServletResponse  HTTP response.
     *
     * @return An ActionForward.
     *
     * @throws IOException  An I/O exception if failed or interrupted I/O operations occurs.
     * @throws ServletException  A ServletException if the servlet has a problem.
     */
    @Override
	public ActionForward execute(ActionMapping mapping, ActionForm actionForm,
                                 HttpServletRequest request,
                                 HttpServletResponse httpServletResponse
                                ) throws IOException, ServletException
    {
        // Gets the login and password from the request.
        String login = request.getParameter("login");
        String password = request.getParameter("password");

        _logger.info("Logon with login : " + login);

        SessionContext sessionContext = null;
        UserContext userContext = null;
        HttpSession session = null;
        ActionMessages msgErrors = new ActionMessages();

        try
        {
            // Gets the session.
            session = request.getSession();
            // Gets the session context.
            sessionContext = SessionContext.getInstance(session);
            // Gets the user context.
            userContext = sessionContext.getUserContext();

            // removes the error message from the session
        	session.removeAttribute("Error_Login");
        	
            // Generates an error if the login is empty.
            if ((login == null) || (login.trim().compareToIgnoreCase("") == 0))
            {
                msgErrors.add(ActionMessages.GLOBAL_MESSAGE,
                              new ActionMessage("errors.required", "Login")
                             );
                //saveErrors(request, msgErrors);
                
            }

            // Generates an error if the password is empty.
            if ((password == null) ||
                    (password.trim().compareToIgnoreCase("") == 0)
               )
            {
                msgErrors.add(ActionMessages.GLOBAL_MESSAGE,
                              new ActionMessage("errors.required", "Password")
                             );
                //saveErrors(request, msgErrors);
            }

            // Generates an error if the login contains '*'.
            if ((login != null) && (login.indexOf("*") != -1))
            {
                msgErrors.add(ActionMessages.GLOBAL_MESSAGE,
                              new ActionMessage("errors.login.star")
                             );
                //saveErrors(request, msgErrors);
            }

            // If errors are generated, returns the logon page.
            if (msgErrors.size() != 0)
            {
            	session.setAttribute("Error_Login", msgErrors);
                return (mapping.getInputForward());
            }


            /*
             * Checks the number of connection try
             */
            if ((AppliParametersManager.getInstance().hasLogonTrialLimit()) &&
                    (userContext.getLogonCounter() >= AppliParametersManager.getInstance()
                                                                                .getMaxLogonTrial())
               )
            {
                msgErrors.add(ActionMessages.GLOBAL_MESSAGE,
                              new ActionMessage("error.logon.maxtrial",
                                                new Integer(AppliParametersManager.getInstance()
                                                                                  .getMaxLogonTrial()
                                                           )
                                               )
                             );
                //saveErrors(request, msgErrors);

                session.setAttribute("Error_Login", msgErrors);
                return (mapping.findForward("error"));
            }

            // Calls the StandardService to log on.
            StandardService.logon(login, password, userContext);

            /*
            * Suppression de l'objet utilisateur du cache
            * pour obliger le chargement de cet objet avec la connexion utilisateur
            */
            userContext.getCache().remove(userContext.getDn());

            // Gets the user profiles
            List profilesList = userContext.getProfiles();
            _logger.info("Found profiles : " + profilesList.size());

            // Returns the profiles page URI if the user has several profiles.
            if (profilesList.size() == 1)
            {
                _logger.info("One profile : " + profilesList.get(0).toString());

                JBProfile profile = userContext.getJbProfile();
                Person user = (Person) userContext.getJbUser();
                user.setProfile(profile.getName());
                userContext.setJbUser(user);

                // Sets the user object in the session.
                session.setAttribute("user", userContext.getJbUser());
                
                // Initializes the navigation
                TreeNode treeNode =
                    ViewGenerator.generateTreeView(sessionContext.getUserContext());
                session.setAttribute("defaultTreeNode", treeNode);

                GenerateTree.getInstance().setMenuCornerMinusUri(request.getContextPath() + "/menu_corner_minus.gif");
                GenerateTree.getInstance().setMenuCornerPlusUri(request.getContextPath() + "/images/menu_corner_plus.gif");
                GenerateTree.getInstance().setMenuTeeMinusUri(request.getContextPath() + "/images/menu_tee_minus.gif");
                GenerateTree.getInstance().setMenuTeePlusUri(request.getContextPath() + "/images/menu_tee_plus.gif");
                GenerateTree.getInstance().setMenuBarUri(request.getContextPath() + "/images/menu_bar.gif");
                GenerateTree.getInstance().setMenuCornerUri(request.getContextPath() + "/images/menu_corner.gif");
                GenerateTree.getInstance().setMenuTeeUri(request.getContextPath() + "/images/menu_tee.gif");
                GenerateTree.getInstance().setMenuPixelUri(request.getContextPath() + "/images/menu_pixel.gif");

                String tree =
                    GenerateTree.getInstance().processTree(treeNode.getDefaultMutableTreeNode(),
                                                           null
                                                          );
                session.setAttribute("treeview", tree);
                

                return (mapping.findForward("success_oneprofile"));
            }
            else
            {
            	// Sorts the profile
            	Comparator comp = new Comparator()
                {
                    @Override
					public int compare(final Object obj1, final Object obj2)
                    {
                        try
                        {
                        	if ((obj1 != null) && (obj2 != null)
                        		&& (obj1 instanceof JBProfile)
                        		&& (obj2 instanceof JBProfile))
                        	{
                        		String name1 = ((JBProfile)obj1).getName();
                        		String name2 = ((JBProfile)obj2).getName();
                                return name1.compareToIgnoreCase(name2);
                            }
                            else
                            {
                                return -1;
                            }
                        }
                        catch (Exception e)
                        {
                            return -1;
                        }
                    }
                };
                Collections.sort(profilesList, comp);
                userContext.setProfiles(profilesList);
            	
                // Sets the user object in the session.
                session.setAttribute("user", userContext.getJbUser());

                return (mapping.findForward("success"));
            }
        }
        catch (AuthenticationFailureException se)
        {
            _logger.info(MessageUtil.formatMessage("MSG_ERROR_LOGON", login));

            //L'utilisateur n'est pas correctement logg�, 
            // on lui retourne une page d'erreur
            // verif si le nombre max d'essai de logon est depasse
            if ((AppliParametersManager.getInstance().hasLogonTrialLimit()) &&
                    (userContext.getLogonCounter() >= AppliParametersManager.getInstance()
                                                                                .getMaxLogonTrial())
               )
            {
                // l'utilisateur n'a plus le droit de reessayer
                // message d'erreur d�finitif
                // Pour empecher vraiment l'utilisateur � se reconnecter
                // il faut persister cette information ! Mais on ne le fera pas
                // ici                                                                                    
                msgErrors.add(ActionMessages.GLOBAL_MESSAGE,
                              new ActionMessage("error.logon.maxtrial",
                                                new Integer(AppliParametersManager.getInstance()
                                                                                  .getMaxLogonTrial()
                                                           )
                                               )
                             );
                saveErrors(request, msgErrors);
                return (mapping.findForward("error"));
            }

            msgErrors.add(ActionMessages.GLOBAL_MESSAGE,
                          new ActionMessage("error.auth.failed")
                         );
            saveErrors(request, msgErrors);

            return (mapping.findForward("error"));
        }
        catch (Exception se)
        {
            se.printStackTrace();

            _logger.error(se.getMessage());
            _logger.error(MessageUtil.formatMessage("error.service.unknown"));
            msgErrors.add(ActionMessages.GLOBAL_MESSAGE,
                          new ActionMessage("error.service.unknown")
                         );
            saveErrors(request, msgErrors);
            
            return (mapping.findForward("error"));
        }
    }
}
